package com.zhucan.account.application.query.impl;

import com.zhucan.account.infrastructure.db.entity.AccountPO;
import com.zhucan.account.infrastructure.exception.AccountNotAccessException;
import com.zhucan.account.infrastructure.db.AccountRepository;
import com.zhucan.account.application.query.AccountQueryService;
import com.zhucan.account.application.query.converter.AccountDTOConverter;
import com.zhucan.account.application.query.dto.AccountBalanceDTO;
import com.zhucan.account.application.query.dto.AccountDTO;
import com.zhucan.account.application.query.dto.PageDTO;
import com.zhucan.account.application.query.qry.AccountBalanceQry;
import com.zhucan.account.application.query.qry.AccountQry;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * author: zhuCan
 * date: 2020/8/4 20:08
 * description:
 */
@Service
@AllArgsConstructor
public class AccountQueryServiceImpl implements AccountQueryService {

  private AccountRepository repository;

  private AccountDTOConverter converter;

  @Override
  public PageDTO<AccountDTO> page(AccountQry qry) {

    Pageable pageable = qry.pageable();

    Specification<AccountPO> specification = (root, query, builder) -> {

      List<Predicate> predicates = new ArrayList<>();
      builder.createQuery();
      if (StringUtils.isNotBlank(qry.getAccount())) {
        predicates.add(builder.like(root.get("account").as(String.class), "%" + qry.getAccount() + "%"));
      }
      if (StringUtils.isNotBlank(qry.getCellphone())) {
        predicates.add(builder.like(root.get("cellphone").as(String.class), "%" + qry.getCellphone() + "%"));
      }
      if (StringUtils.isNotBlank(qry.getIdentityCard())) {
        predicates.add(builder.like(root.get("identityCard").as(String.class), "%" + qry.getIdentityCard() + "%"));
      }
      if (qry.getRegisterStartTime() != null) {
        predicates.add(builder.greaterThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), qry.getRegisterStartTime()));
      }

      if (qry.getRegisterEndTime() != null) {
        predicates.add(builder.lessThanOrEqualTo(root.get("createTime").as(LocalDateTime.class), qry.getRegisterEndTime()));
      }


      return builder.and(predicates.toArray(new Predicate[predicates.size()]));
    };

    Page<AccountPO> pageList = repository.findAll(specification, pageable);

    return PageDTO.of(pageList.map(converter::convertDTO));
  }

  @Override
  public AccountBalanceDTO balance(AccountBalanceQry qry) {
    Optional<AccountPO> optionalAccount = repository.findByAccountAndPassword(qry.getAccount(), qry.getPassword());

    AccountPO accountPO = optionalAccount.orElseThrow(() -> new AccountNotAccessException("账户密码错误"));
    return new AccountBalanceDTO(accountPO.getAmount());
  }
}
